//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdlib.h>
#pragma hdrstop

#include "Eic.h" //Pour EICDisplayException
#include "CGBox.h"
#define MODULE_TAG 1004

#define LEFT_CAPTION           8
#define HAUT_CONTOUR_GROUPBOX  5 //Coordonnée du trait qui délimite le haut du GroupBox
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//
static inline void ValidCtrCheck(CGroupBox *)
    {
    new CGroupBox(NULL);
    }


//////////////////////////////////////
//
// CGROUPBOX
//
// Fonction: Constructeur
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
__fastcall CGroupBox::CGroupBox(TComponent* Owner)
    : TCustomGroupBox(Owner)
   {
   try
      {
      FReadOnly           = false;
      inherited::Color    = clBtnFace;
      hrgnZoneVisible     = NULL;
      bIsVraimentVisible  = false;
      m_bBordHautTransparent = true;
      }
    catch(Exception &e)
       {
       EICDisplayException(TAG(10), e);
       }
    }


__fastcall CGroupBox::~CGroupBox(void)
   {
   }
//////////////////////////////////////
//
// SetCaption
//
// Fonction: Initialise le Caption
//
// P.E.: aCaption
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGroupBox::SetCaption( const AnsiString aCaption )
    {
    inherited::Caption  = aCaption;
    DefinirRegionVisible(); //Lorsque le texte change, la région affichée change aussi
    }



//////////////////////////////////////
//
// SetColor
//
// Fonction: Initialise la couleur du fond
//
// P.E.: CColor
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGroupBox::SetColor( TColor CColor )
    {
    inherited::Color = CColor;
    Repaint();
    }



//////////////////////////////////////
//
// SetEnabled
//
// Fonction: Initialise Enabled
//
// P.E.: Enabled
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGroupBox::SetEnabled( bool bEnabled )
   {
   int i;
   inherited::Enabled  = bEnabled;

   for(i = 0; i < ControlCount ; i++)
      Controls[i]->Enabled = bEnabled;

   if (!Text.IsEmpty())
      Refresh(); //Indispensable pour que la couleur du texte soit rafraîchie
   }

//////////////////////////////////////
//
// SetReadOnly
//
// Fonction: Initialise le GBox & ses enfants a ReadOnly
//
// P.E.: bReadOnly
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGroupBox::SetReadOnly( bool bReadOnly )
   {
   int i;
   FReadOnly = bReadOnly;

//   if( ComponentState.Contains( csDesigning )) //Seulement en conception ?????? Fonctionnement différent du ReadOnly !!!!!!
      {
      for(i = 0; i < ControlCount ; i++)
         if(Controls[ i ]->ClassName()[1] == 'C')
            SendMessage(((TWinControl*)Controls[i])->Handle, WM_READONLY, (int)bReadOnly, 0L );
      }
    }

//////////////////////////////////////
//
// GetCaption
//
// Fonction: Retourne le Caption
//
// P.E.: AUCUN
//
// P.S.: Caption
//
//////////////////////////////////////
AnsiString __fastcall CGroupBox::GetCaption() /*const*/
    {
    return( inherited::Caption );
    }



//////////////////////////////////////
//
//
//
// Fonction: Retourne la couleur en cours du fond
//
// P.E.: AUCUN
//
// P.S.: Color
//
//////////////////////////////////////
TColor __fastcall CGroupBox::GetColor() const
    {
   return( inherited::Color );
    }



//////////////////////////////////////
//
// GetEnabled
//
// Fonction:
//
// P.E.: AUCUN
//
// P.S.: Enabled
//
//////////////////////////////////////
bool __fastcall CGroupBox::GetEnabled()
    {
    return( inherited::Enabled );
    }

//////////////////////////////////////
//
// WndProc
//
// Fonction: Intercepte les evenements
//
// P.E.: Le message
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CGroupBox::WndProc( TMessage &Message )
   {
   switch( Message.Msg )
      {
      case WM_ENABLE:
         {
         Enabled = (bool)Message.WParam;
         break;
         }

      case WM_READONLY:
         {
         ReadOnly = (bool)Message.WParam;
         break;
         }

      case WM_CREATE:
         {
         TabStop          = false;
         inherited::TabStop    = false;
         break;
         }
      }

    inherited::WndProc( Message );

    switch(Message.Msg)
       {
       case WM_SETFONT:
       case WM_SIZE:
         //Lorsque la fonte change (Gras / Non gras), la position du texte change
         //ou lorsque la taille du composant change
         // => On doit redélimiter la zone visible
         DefinirRegionVisible();
         break;

       case WM_PAINT:
         /// On valide la région qui ne sera pas invisible
         /////////////////////////////////////////////////////////////////////////////
         if (!bIsVraimentVisible)
            {
            bIsVraimentVisible = true;
            DefinirRegionVisible();
            }
          break;
       }
    }

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CGroupBox::SetBordHautTransparent(bool bBordHautTransparent)
{
try
   {
/*      BeginPath(Canvas->Handle);

      ExtTextOut(Canvas->Handle, 0, 0, 0, NULL, "TEQSTSTTSETT", 8, NULL);
      Rectangle(Canvas->Handle, 0, 0, 20, 10);

      EndPath(Canvas->Handle);

      if (PathToRegion(Canvas->Handle))
         ShowMessage("OK");*/

   if (m_bBordHautTransparent == bBordHautTransparent)
      return;

   m_bBordHautTransparent = bBordHautTransparent;

   DefinirRegionVisible();
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(200), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CGroupBox::DefinirRegionVisible()
{
try
   {
   if (!bIsVraimentVisible)
      return;

/*   if (m_bBordHautTransparent)
      {
      TSize SizeCaption = Canvas->TextExtent(Caption.IsEmpty() ? AnsiString("1") : Caption);

      //On ajoute à la zone visible le GroupBox (hrgnZoneVisible sera désalloué par le system => conférer aide de SetWindowRgn)
      hrgnZoneVisible = CreateRectRgn(0,
                                      SizeCaption.cy/2-1,
                                      Width,
                                      Height);

      IntersectClipRect(Canvas->Handle,
                         0,
                         SizeCaption.cy/2-1,
                         Width,
                         Height);

      // THE FIX: by setting the background mode
      // to transparent, the region is the text itself
//      SetBkMode(Canvas->Handle, TRANSPARENT);
//      Canvas->Font->Color = clBtnShadow;

      BeginPath(Canvas->Handle);

//      TRect R = Rect(8, 0, 0, Canvas->TextHeight('0'));
      //On  dimensionne correctement le rectangle
//      DrawText(Canvas->Handle, Text.c_str(), Text.Length(), &R, DT_SINGLELINE);
//      Canvas->TextOut(8, 0, Text);
//      Rectangle(Canvas->Handle, 0, 0, 20, 10);
//      TextOut(Canvas->Handle, 0, 0, "TEQSTSTTSETT", 8);

      ExtTextOut(Canvas->Handle, 0, 0, 0, NULL, "TEQSTSTTSETT", 8, NULL);

      EndPath(Canvas->Handle);

      if (PathToRegion(Canvas->Handle))
         ShowMessage("OK");

      ExtTextOut(Canvas->Handle, 0, 0, 0, NULL, "TEQSTSTTSETT", 8, NULL);
//      TextOut(Canvas->Handle, 0, 0, "TEQSTSTTSETT", 8);


      SelectClipPath(Canvas->Handle, RGN_OR);
      GetClipRgn(Canvas->Handle, hrgnZoneVisible);

      // On valide la région lors du dessin => Permet de masquer la zone grise du haut.
      SetWindowRgn(inherited::Handle, hrgnZoneVisible, true);

      if (DeleteObject(hrgnZoneVisible))
         hrgnZoneVisible = NULL;
      }
   else
      //Tout le groupbox sera visible
      SetWindowRgn(inherited::Handle, NULL, true);
  */


   if (m_bBordHautTransparent)
      {
      HRGN hrgnZoneAAjouter = NULL;
      int x;
      int y;
      int RGBCouleurFond = GetPixel(Canvas->Handle, 0, 0); //On ne prend pas Color car pour une raison indéterminée, elle est différente de la couleur de fond en affichage 16 bits.
      int iLargeurTexte;
      int iDebutHautGroupBox;
      TSize SizeCaption;

/* La région est gérée par le composant (cf aide de SetWindowRgn)
      if (hrgnZoneVisible)
         {
         if (DeleteObject(hrgnZoneVisible))
            hrgnZoneVisible = NULL;
         ASSERT(!hrgnZoneVisible); //Le DeleteObject doit être réussi
         }*/

      SetWindowRgn(inherited::Handle, NULL, true);
      Update(); //Rafraîchissement pour que les zones d'écritures soient détectées.

      SizeCaption = Canvas->TextExtent(Caption.IsEmpty() ? AnsiString("1") : Caption);

      //On ajoute à la zone visible le GroupBox (hrgnZoneVisible sera désalloué par le system => conférer aide de SetWindowRgn)
      hrgnZoneVisible = CreateRectRgn(0,
                                      SizeCaption.cy/2-1,
                                      Width,
                                      Height);

      for(x = LEFT_CAPTION+1 ; x < LEFT_CAPTION+1+SizeCaption.cx ; x++)
         for(y=0 ; y < SizeCaption.cy/2 ; y++)
            if ((int)GetPixel(Canvas->Handle, x, y) != RGBCouleurFond)
               {
               hrgnZoneAAjouter = CreateRectRgn(x,
                                                y,
                                                x+1,
                                                y+1);
               if (hrgnZoneVisible)
                  {
                  CombineRgn(hrgnZoneVisible, hrgnZoneVisible, hrgnZoneAAjouter, RGN_OR);
                  if (DeleteObject(hrgnZoneAAjouter))
                     hrgnZoneAAjouter = NULL;

                  ASSERT(!hrgnZoneAAjouter); //Le DeleteObject doit être réussi
                  }
               else
                  hrgnZoneVisible = hrgnZoneAAjouter;
               }

      // On valide la région lors du dessin => Permet de masquer la zone grise du haut.
      SetWindowRgn(inherited::Handle, hrgnZoneVisible, true);
      }
   else
      //Tout le groupbox sera visible
      SetWindowRgn(inherited::Handle, NULL, true);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(210), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CGroupBox::Paint(void)
{
try
   {
   inherited::Paint();

   /// Lorsque le composant est inactif, le texte du GroupBox est écrit en conséquence
   /////////////////////////////////////////////////////////////////////////////
   if (!Text.IsEmpty() && !Enabled)
      {
      TRect R;
      R = Rect(8, 0, 0, Canvas->TextHeight('0'));

      //On  dimensionne correctement le rectangle
      DrawText(Canvas->Handle, Text.c_str(), Text.Length(), &R, DT_SINGLELINE | DT_CALCRECT);

      //On écrit le texte une première fois, en décalé et en clair => ce qui fait son "ombre"
      Canvas->Font->Color = clBtnHighlight;
      OffsetRect(&R, 1, 1);
      DrawText(Canvas->Handle, Text.c_str(), Text.Length(), &R, DT_SINGLELINE);

      //On écrit le texte une seconde fois, à sa position d'origine
      SetBkMode(Canvas->Handle, TRANSPARENT);
      OffsetRect(&R, -1, -1);
      Canvas->Font->Color = clBtnShadow;
      DrawText(Canvas->Handle, Text.c_str(), Text.Length(), &R, DT_SINGLELINE);
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(220), e);
   }
}

namespace Cgbox
    {
    void __fastcall PACKAGE Register()
        {
        TComponentClass classes[1] = {__classid(CGroupBox)};
        RegisterComponents("EIC Ctrlstd", classes, 0);
        }
    }

